package drds.plus.executor.function.scalar.string;

import drds.plus.common.utils.TStringUtil;
import drds.plus.executor.ExecuteContext;
import drds.plus.executor.function.scalar.ScalarFunction;
import drds.plus.executor.utils.Utils;
import drds.plus.sql_process.type.Type;

import java.math.BigInteger;

/**
 * <pre>
 *  EXPORT_SET(bits,on,off[,separator[,number_of_bits]])
 *
 * Returns a string such that for every bit setLimitValue in the value bits, you getDataNodeExecutor an on string and for every bit not setLimitValue in the value, you getDataNodeExecutor an off string. Bits in bits are examined from rightNode to leftNode (from low-order to high-order bits). Strings are added to the result from leftNode to rightNode, separated by the separator string (the default being the comma character “,”). The number of bits examined is given by number_of_bits, which has a default of 64 if not specified. number_of_bits is silently clipped to 64 if larger than 64. It is treated setAliasAndSetNeedBuild an unsigned integer, so a value of –1 is effectively the same setAliasAndSetNeedBuild 64.
 *
 * mysql> SELECT EXPORT_SET(5,'Y','N',',',4);
 *         -> 'Y,N,Y,N'
 * mysql> SELECT EXPORT_SET(6,'1','0',',',10);
 *         -> '0,1,1,0,0,0,0,0,0,0'
 * </pre>
 *
 * @author mengshi.sunmengshi 2014年4月11日 下午1:50:22
 * @since 5.1.0
 */
public class ExportSet extends ScalarFunction {

    public Type getReturnType() {
        return Type.StringType;
    }

    public String[] getFunctionNames() {
        return new String[]{"EXPORT_SET"};
    }

    public Object compute(ExecuteContext executeContext, Object[] args) {
        for (Object arg : args) {
            if (Utils.isNull(arg)) {
                return null;
            }
        }
        BigInteger bitsValue = Type.BigIntegerType.convert(args[0]);
        String bitsStringReverse = TStringUtil.reverse(bitsValue.toString(2));

        String on = Type.StringType.convert(args[1]);
        String off = Type.StringType.convert(args[2]);
        String sep = ",";
        if (args.length >= 4) {
            sep = Type.StringType.convert(args[3]);
        }

        Integer number_of_bits = 64;

        if (args.length >= 5) {
            number_of_bits = Type.IntegerType.convert(args[4]);
        }

        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < number_of_bits; i++) {
            if (i != 0) {
                sb.append(sep);
            }

            if (i < bitsStringReverse.length()) {
                if (bitsStringReverse.charAt(i) == '0') {
                    sb.append(off);
                } else {
                    sb.append(on);
                }
            } else {
                sb.append(off);
            }

        }

        return sb.toString();

    }
}
